/*
|-----------------------------------------------------------------------------|
| Overall ANTLR Grammar File Structure                                        |
|-----------------------------------------------------------------------------|
| «grammarType» grammar name;
|   «optionsSpec»     = options { ... }
|   «tokensSpec»      = tokens { ... }
|   «attributeScopes» = «@action-scope-name::action-name» { ... }
|   «actions»
|   // rules
|   rule1 : ... ;
|   rule2 : ... ;
|   ...
|_____________________________________________________________________________|
|   «grammarType»         = ( lexer | parser | tree | <empty> )
|   «optionsSpec»         = options { ... }
|   «tokensSpec»          = tokens { ... }
|   «attributeScopes»     = 
|   «actions»             = @«action-scope-name»::«action-name» { ... }
|    «action-scope-name» = ( lexer | parser | tree | <empty> = parser )
|    «action-name»       = ( header | members | rulecatch | synpredgate )
|-----------------------------------------------------------------------------|
*/
lexer grammar XMLLexer;

  options {
    language = Java;
  }// options

  @lexer::header {
    package pl.p04;
    import pl.p04.MyToken;
  }// header
  @lexer::members {
    /**
     *  The standard method called to automatically emit a token at the outermost lexical rule.
     *  The token object should point into the char buffer start..stop. If there is a text override
     *  in 'text', use that to set the token's text. Override this method to emit custom Token objects.
     *
     *  If you are building trees, then you should also override Parser or TreeParser.getMissingSymbol(). 
     *
     *  References:
     *   http://www.antlr.org/api/Java/classorg_1_1antlr_1_1runtime_1_1_lexer.html
     */
    @Override
    public Token emit() {
      MyToken t = new MyToken(input, state.type, state.channel, state.tokenStartCharIndex, getCharIndex()-1);
      t.setLine(state.tokenStartLine);
      t.setText(state.text);
      t.setCharPositionInLine(state.tokenStartCharPositionInLine);
      emit(t);
      // Tratar nuevo atributo
      if (input.getClass().getName().matches(".*ANTLRFileStream.*$"))
        t.setFileName(this.getSourceName());
      else
        t.setFileName("InputStream");
      return t;
    }// emit

  }// members

//= Rules ====================================================================|
  /* Nueva línea */
  fragment NewLine: '\r'? '\n';

  /* Dígitos */
  fragment Digit: '0'..'9';

  /* Letras */
  fragment Letter: ('a'..'z') | ('A'..'Z') | '_';

  /* Espacios */
  Space : (' ' | '\t' | NewLine ) { $channel=HIDDEN; skip(); };

  /* Números */
  Number : (Digit)+ ;

  /* Identificadores */
  Id: Letter (Letter | Digit)*;
  
 /* 
  //Reglas explícitas
  InitLibrary   : "<biblioteca>";
  InitBook      : "<libro>";
  InitTitle     : "<titulo>";
  InitAuthor    : "<autor>";
  InitEditorial : "<editorial>";
  EndLibrary    : "</biblioteca>";
  EndBook       : "</libro>";
  EndTitle      : "</titulo>";
  EndAuthor     : "</autor>";
  EndEditorial  : "</editorial>";
*/

  // Reglas implícitas
   OpenTag  : '<'  (Letter)+ '>';
   CloseTag : '</' (Letter)+ '>';  

  /* Cadenas */
  String: '\"' (~('\"'))* '\"';
   
  /* Comentarios */
  Comment: '<!--' (options {greedy=false;} : ( Comment | . ))* '-->'
      { $channel=HIDDEN; skip(); };